package com.qs.javame.thread.join;

import java.util.concurrent.TimeUnit;

/**
 * thread.join()：一个线程中执行thread.join()表示这个线程会等待thread执行完成后，然后在join()方法处返回；
 * <p>
 * 实现原理：join()的源码实际上是通过wait()实现的，所以实际上还是等待/唤醒机制；
 */
public class TestJoin {
    public static void main(String[] args) {

        //记录上一个线程
        Thread prevThread = Thread.currentThread();

        //开启10个线程，thread-0等待main执行完，thread-1等待thread-0执行完。。。，
        // 所以最先执行的是main，然后是thread-0，thread-1。。。，thread-9
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(new Domino(prevThread), "Thread-" + i);
            thread.start();
            prevThread = thread;
        }

        System.out.println(Thread.currentThread().getName() + "-最先执行么~");
    }

    static class Domino implements Runnable {

        private Thread thread;

        //构造方法中的thread对象一次为前一个开始执行的thread对象
        public Domino(Thread thread) {
            this.thread = thread;
        }

        @Override
        public void run() {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName() + " terminated~");
        }
    }
}

/**
 * 测试：main线程等待thread线程执行完成后返回
 *
 * 源码分析执行过程：
 *  1、main线程中，创建thread线程，并调用thread.start()方法，运行thread线程；
 *  2、main线程中执行thread.join()方法，源码中体现为：
 *  join()方法为同步方法，锁对象为this，这个this就是thread对象，main线程执行thread.join()方法，即获取到锁对象(thread)，
 *  在this.wait(0)处等待被唤醒。
 *  3、main线程什么时候在wait(0)处被唤醒？这部分由jvm底层实现，在thread线程执行完成后(状态为TERMINATED)，会调用thread.notifyAll()
 *  方法唤醒等待在该锁对象上的线程，也就是main线程(jvm中代码表现为：lock.notify_all(thread))，此时main线程从wait(0)处返回，继而完成
 *  main线程。
 */
class JoinDemo {
    public static void main(String[] args) {

        RR rr = new RR();
        Thread thread = new Thread(rr);
        thread.start();

        try {
            //main线程调用thread.join()方法，等待thread线程执行完成后，再开始继续执行main线程中任务
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("main执行完毕。。");
    }


    private static class RR implements Runnable {

        @Override
        public void run() {
            try {
                TimeUnit.SECONDS.sleep(5);
                System.out.println(Thread.currentThread().getName() + "-执行完了~");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


//测试：this是什么？this就是实例化的对象
class TestThis {

    private Integer num = 2;

    public TestThis() {
        System.out.println(this);
    }

    public TestThis getThis(){
        return this;
    }


    public static void main(String[] args) {
        TestThis testThis = new TestThis();
        System.out.println(testThis);
        System.out.println(testThis.getThis());
    }

}
